package com.jasiri.project.utils.http;

import android.os.Handler;
import android.os.Looper;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

import javax.net.ssl.HttpsURLConnection;

/**
 * Sikadwa
 * @Author wwdeng
 * @CreateTime: 2025/4/1 10:42
 * @Annotation： HttpsURLConnection 网络请求
 */
public class HttpRequestBuilder {
    private static final Handler mainHandler = new Handler(Looper.getMainLooper());
    private String url;
    private String method = "GET";
    private Map<String, String> headers;
    private Map<String, String> params;
    private String body;
    private int connectTimeout = 5000;
    private int readTimeout = 5000;

    public interface Callback {
        void onSuccess(String response);
        void onFailure(int code,String msg);
        void onFinished();
    }

    public HttpRequestBuilder url(String url) {
        this.url = url;
        return this;
    }

    public HttpRequestBuilder method(String method) {
        this.method = method.toUpperCase();
        return this;
    }

    public HttpRequestBuilder addHeader(String key, String value) {
        if (headers == null) {
            headers = new HashMap<>();
        }
        headers.put(key, value);
        return this;
    }

    public HttpRequestBuilder addParam(String key, String value) {
        if (params == null) {
            params = new HashMap<>();
        }
        params.put(key, value);
        return this;
    }

    public HttpRequestBuilder body(String body) {
        this.body = body;
        return this;
    }

    public HttpRequestBuilder timeouts(int connectTimeout, int readTimeout) {
        this.connectTimeout = connectTimeout;
        this.readTimeout = readTimeout;
        return this;
    }

    /**
     * 普通请求
     * @param callback
     */
    public void execute(final Callback callback) {
        new Thread(() -> {
            HttpsURLConnection urlConnection = null;
            try {
                // 构建URL (如果是GET请求且带参数)
                String fullUrl = url;
                if (method.equals("GET") && params != null && !params.isEmpty()) {
                    fullUrl += "?" + buildQueryString(params);
                }

                URL url = new URL(fullUrl);
                urlConnection = (HttpsURLConnection) url.openConnection();
                urlConnection.setRequestMethod(method);
                urlConnection.setConnectTimeout(connectTimeout);
                urlConnection.setReadTimeout(readTimeout);
                urlConnection.setRequestProperty("Charset", "UTF-8");
                urlConnection.setRequestProperty("Connection", "Keep-Alive");
                urlConnection.setRequestProperty("Content-Type", "application/json");
                urlConnection.setRequestProperty("Accept", "*/*");
//                urlConnection.setSSLSocketFactory(SSLUtil.INSTANCE.createSSLSocketFactory());
//                urlConnection.setHostnameVerifier(new SSLUtil.TrustAllHostnameVerifier());

                // 设置请求头
                if (headers != null) {
                    for (Map.Entry<String, String> header : headers.entrySet()) {
                        urlConnection.setRequestProperty(header.getKey(), header.getValue());
                    }
                }

                // 如果是POST/PUT请求且有参数或body
                if (method.equals("POST") || method.equals("PUT")) {
                    urlConnection.setDoOutput(true);
                    byte[] outputBytes;

                    if (body != null) {
                        outputBytes = body.getBytes(StandardCharsets.UTF_8);
                    } else if (params != null && !params.isEmpty()) {
                        String postData = buildQueryString(params);
                        outputBytes = postData.getBytes(StandardCharsets.UTF_8);
                    } else {
                        outputBytes = new byte[0];
                    }

                    try (OutputStream outputStream = urlConnection.getOutputStream()) {
                        outputStream.write(outputBytes);
                    }
                }

                int responseCode = urlConnection.getResponseCode();
                String responseMessage = urlConnection.getResponseMessage();
                if (responseCode == HttpURLConnection.HTTP_OK) {
                    String response = readResponse(urlConnection.getInputStream());
                    mainHandler.post(() -> callback.onSuccess(response));
                } else {
                    mainHandler.post(() -> callback.onFailure(responseCode,"HTTP error code: " + responseCode + ",message: "+responseMessage));
                }
            } catch (Exception e) {
                mainHandler.post(() -> callback.onFailure(-1,e.getLocalizedMessage()));
            } finally {
                if (urlConnection != null) {
                    urlConnection.disconnect();
                }
                mainHandler.post(callback::onFinished);
            }
        }).start();
    }

    /**
     * 文件上传
     */
    public void uploadFile(String filePath,Callback callback){
        new Thread(() -> {
            String boundary = UUID.randomUUID().toString();
            String twoHyphens = "--";
            String lineEnd = "\r\n";
            File file = new File(filePath);
            if (!file.exists()){
                mainHandler.post(() -> callback.onFailure(-1,"File not found: " + filePath));
                return;
            }
            HttpsURLConnection urlConnection = null;
            try {
                String fullUrl = url;
                URL url = new URL(fullUrl);
                urlConnection = (HttpsURLConnection) url.openConnection();
                urlConnection.setRequestMethod(method);
                urlConnection.setConnectTimeout(connectTimeout);
                urlConnection.setReadTimeout(readTimeout);
                urlConnection.setRequestProperty("Charset", "UTF-8");
                urlConnection.setRequestProperty("Connection", "Keep-Alive");
                urlConnection.setRequestProperty("Content-Type", "application/json");
                urlConnection.setRequestProperty("Accept", "*/*");
//                urlConnection.setSSLSocketFactory(SSLUtil.INSTANCE.createSSLSocketFactory());
//                urlConnection.setHostnameVerifier(new SSLUtil.TrustAllHostnameVerifier());
                // 设置请求头
                if (headers != null) {
                    for (Map.Entry<String, String> header : headers.entrySet()) {
                        urlConnection.setRequestProperty(header.getKey(), header.getValue());
                    }
                }
                urlConnection.setRequestProperty("Content-Type", "multipart/form-data; boundary="+boundary);
                String contentType = URLConnection.guessContentTypeFromName(file.getName());
                if (contentType == null){
                    contentType = "application/octet-stream";
                }
                DataOutputStream outputStream = new DataOutputStream(urlConnection.getOutputStream());
                // 写入 multipart 表单头部
                outputStream.writeBytes(twoHyphens+boundary+lineEnd);
                outputStream.writeBytes("Content-Disposition: form-data; name=\"image\"; filename="+file.getName()+lineEnd);
                outputStream.writeBytes("Content-Type:"+contentType+lineEnd);
                outputStream.writeBytes(lineEnd);

                // 读取文件数据
                FileInputStream fileInputStream = new FileInputStream(file);
                byte[] buffer = new byte[4096];
                int bytesRead;
                // 使用循环读取文件数据
                while ((bytesRead = fileInputStream.read(buffer)) != -1) {
                    outputStream.write(buffer,0,bytesRead);
                }
                fileInputStream.close();

                outputStream.writeBytes(lineEnd);
                outputStream.writeBytes(twoHyphens+boundary+twoHyphens+lineEnd);
                outputStream.flush();
                outputStream.close();

                try {
                    int responseCode = urlConnection.getResponseCode();
                    String responseMessage = urlConnection.getResponseMessage();
                    if (responseCode == HttpURLConnection.HTTP_OK) {
                        String response = readResponse(urlConnection.getInputStream());
                        mainHandler.post(() -> callback.onSuccess(response));
                    } else {
                        mainHandler.post(() -> callback.onFailure(responseCode,"HTTP error code: " + responseCode + ",message: "+responseMessage));
                    }
                } catch (Exception e) {
                    mainHandler.post(() -> callback.onFailure(-1,e.getLocalizedMessage() == null ? "Unknown error" : e.getLocalizedMessage()));
                } finally {
                    urlConnection.getInputStream().close();
                    urlConnection.disconnect();
                    mainHandler.post(callback::onFinished);
                }
            } catch (Exception e){
                mainHandler.post(() -> callback.onFailure(-1,e.getLocalizedMessage() == null ? "Unknown error" : e.getLocalizedMessage()));
                mainHandler.post(callback::onFinished);
            }
        }).start();
    }

    private String buildQueryString(Map<String, String> params) {
        StringBuilder result = new StringBuilder();
        for (Map.Entry<String, String> entry : params.entrySet()) {
            if (result.length() > 0) {
                result.append("&");
            }
            result.append(entry.getKey());
            result.append("=");
            result.append(entry.getValue());
        }
        return result.toString();
    }

    private String readResponse(InputStream inputStream) throws IOException {
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        StringBuilder response = new StringBuilder();
        String line;
        while ((line = reader.readLine()) != null) {
            response.append(line);
        }
        reader.close();
        return response.toString();
    }
}
